﻿namespace AddressBook.Business.Contact
{
	#region "Using Statements"
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;

	using Csla;
	using Csla.Data;
	using Csla.Validation;

	using AddressBook.Business.Model;
	using AddressBook.Business.Person;
	#endregion

	[Serializable]
	public class FamilyMember : BusinessBase<FamilyMember>, IPerson
	{
		#region "Business Methods"

		#region "Private Static Member Variables"

		private static PropertyInfo<Int32> FamilyIdProperty = RegisterProperty<Int32>(fm => fm.FamilyId);
		private static PropertyInfo<Int32> ContactIdProperty = RegisterProperty<Int32>(fm => fm.ContactId);
		private static PropertyInfo<String> TitleProperty = RegisterProperty<String>(fm => fm.Title);
		private static PropertyInfo<String> FirstNameProperty = RegisterProperty<String>(fm => fm.FirstName);
		private static PropertyInfo<String> MiddleNameProperty = RegisterProperty<String>(fm => fm.MiddleName);
		private static PropertyInfo<String> LastNameProperty = RegisterProperty<String>(fm => fm.LastName);
		private static PropertyInfo<String> SuffixProperty = RegisterProperty<String>(fm => fm.Suffix);
		private static PropertyInfo<SmartDate> ModifiedDateProperty = RegisterProperty<SmartDate>(a => a.ModifiedDate);

		#endregion

		#region "Public Properties"

		#region "FamilyMember Properties"

		public Int32 FamilyId
		{
			get { return GetProperty(FamilyIdProperty); }
			internal set { LoadProperty(FamilyIdProperty, value); }
		}

		public Int32 ContactId
		{
			get { return GetProperty(ContactIdProperty); }
			internal set { LoadProperty(ContactIdProperty, value); }
		}

		public String ModifiedDate
		{
			get { return GetProperty(ModifiedDateProperty).ToString(); }
		}

		#endregion

		#region "Contact Properties"

		public String Title
		{
			get { return GetProperty(TitleProperty); }
			internal set { SetProperty(TitleProperty, value); }
		}

		public String FirstName
		{
			get { return GetProperty(FirstNameProperty); }
			internal set { SetProperty(FirstNameProperty, value); }
		}

		public String MiddleName
		{
			get { return GetProperty(MiddleNameProperty); }
			internal set { SetProperty(MiddleNameProperty, value); }
		}

		public String LastName
		{
			get { return GetProperty(LastNameProperty); }
			internal set { SetProperty(LastNameProperty, value); }
		}

		public String Suffix
		{
			get { return GetProperty(SuffixProperty); }
			internal set { SetProperty(SuffixProperty, value); }
		}

		public string FormalName
		{
			get
			{
				if (String.IsNullOrEmpty(this.MiddleName))
				{
					return String.Format("{0} {1} {2} {3}", this.Title, this.FirstName, this.LastName, this.Suffix).Trim();
				}

				return String.Format("{0} {1} {2} {3} {4}", this.Title, this.FirstName, this.MiddleName, this.LastName, this.Suffix).Trim();
			}
		}

		public string FullName
		{
			get
			{
				if (String.IsNullOrEmpty(this.MiddleName) && String.IsNullOrEmpty(this.Suffix))
				{
					return String.Format("{0} {1}", this.FirstName, this.LastName);
				}
				else if (!String.IsNullOrEmpty(this.MiddleName) && String.IsNullOrEmpty(this.Suffix))
				{
					return String.Format("{0} {1} {2}", this.FirstName, this.MiddleName, this.LastName);
				}
				else if (String.IsNullOrEmpty(this.MiddleName) && !String.IsNullOrEmpty(this.Suffix))
				{
					return String.Format("{0} {1} {2}", this.FirstName, this.LastName, this.Suffix);
				}

				return String.Format("{0} {1} {2} {3}", this.FirstName, this.MiddleName, this.LastName, this.Suffix);
			}
		}

		public string Name
		{
			get
			{
				return String.Format("{0} {1}", this.FirstName, this.LastName);
			}
		}

		#endregion

		#endregion

		#endregion

		#region "Business Rules"



		#endregion

		#region "Factory Methods"

		internal static FamilyMember NewFamilyMember(Int32 contactId)
		{
			return DataPortal.CreateChild<FamilyMember>(contactId);
		}

		internal static FamilyMember GetFamilyMember(AddressBook.Business.Model.FamilyMember data)
		{
			return DataPortal.FetchChild<FamilyMember>(data);
		}

		private FamilyMember()
		{ /* require use of factory methods */ }

		#endregion

		#region "Data Access"

		protected override void Child_Create()
		{

		}

		private void Child_Create(Int32 contactId)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				AddressBook.Business.Model.Contact contact = ctx.DataContext.Contacts.FirstOrDefault(c => c.Id == contactId);

				using (BypassPropertyChecks)
				{
					this.ContactId = contactId;
					this.Title = contact.Title;
					this.FirstName = contact.FirstName;
					this.MiddleName = contact.MiddleName;
					this.LastName = contact.LastName;
					this.Suffix = contact.Suffix;
				}
			}
		}

		private void Child_Fetch(AddressBook.Business.Model.FamilyMember data)
		{
			using (BypassPropertyChecks)
			{
				this.FamilyId = data.FamilyId;
				this.ContactId = data.ContactId;
				this.Title = data.Contact.Title;
				this.FirstName = data.Contact.FirstName;
				this.MiddleName = data.Contact.MiddleName;
				this.LastName = data.Contact.LastName;
				this.Suffix = data.Contact.Suffix;

				LoadProperty(ModifiedDateProperty, data.ModifiedDate);
			}
		}

		private void Child_Insert(Family family)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// insert family member data
				using (BypassPropertyChecks)
				{
					AddressBook.Business.Model.FamilyMember familyMember = new AddressBook.Business.Model.FamilyMember();

					this.FamilyId = family.Id;

					familyMember.FamilyId = this.FamilyId;
					familyMember.ContactId = this.ContactId;
					familyMember.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.FamilyMembers.InsertOnSubmit(familyMember);
					ctx.DataContext.SubmitChanges();

					LoadProperty(ModifiedDateProperty, familyMember.ModifiedDate);
				}
			}
		}

		private void Child_Update()
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// update family member data
				using (BypassPropertyChecks)
				{
					AddressBook.Business.Model.FamilyMember familyMember = ctx.DataContext.FamilyMembers.First(fm => fm.FamilyId == this.FamilyId && fm.ContactId == this.ContactId);

					familyMember.FamilyId = this.FamilyId;
					familyMember.ContactId = this.ContactId;
					familyMember.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.SubmitChanges();
				}
			}
		}

		private void Child_DeleteSelf(Family family)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				AddressBook.Business.Model.FamilyMember familyMember = ctx.DataContext.FamilyMembers.First(fm => fm.FamilyId == this.FamilyId && fm.ContactId == this.ContactId);

				ctx.DataContext.FamilyMembers.DeleteOnSubmit(familyMember);
				ctx.DataContext.SubmitChanges();
			}
		}

		#endregion
	}
}